
package com.glp.work.flow.workflow.plugin.flowable.service.impl;

import com.github.pagehelper.PageInfo;
import com.glp.fbs.api.dto.appInfo.AppUserResp;
import com.glp.fbs.api.dto.user.PersonInfoDto;
import com.glp.fbs.api.dto.user.PersonInfoWithAppReq;
import com.glp.work.flow.constant.*;
import com.glp.work.flow.dto.UserDTO;
import com.glp.work.flow.dto.request.PersonInfoReq;
import com.glp.work.flow.exception.APIException;
import com.glp.work.flow.mapper.*;
import com.glp.work.flow.pojo.*;
import com.glp.work.flow.request.FlowTaskHistoryDTO;
import com.glp.work.flow.request.ProcessStatusRequest;
import com.glp.work.flow.response.UserTaskDto;
import com.glp.work.flow.service.*;
import com.glp.work.flow.utils.DateUtils;
import com.glp.work.flow.workflow.command.CommonEndProcessInstanceCmd;
import com.glp.work.flow.workflow.command.CommonJumpTaskCmd;
import com.glp.work.flow.workflow.command.CommonJumpToUpperTaskCmd;
import com.glp.work.flow.workflow.plugin.flowable.constant.FlowConstant;
import com.glp.work.flow.workflow.plugin.flowable.dto.FlowDataListDTO;
import com.glp.work.flow.workflow.plugin.flowable.service.FlowProcessDefinitionService;
import com.glp.work.flow.workflow.plugin.flowable.service.FlowTaskService;
import com.glp.work.flow.workflow.plugin.flowable.util.DateUtil;
import com.glp.work.flow.workflow.plugin.flowable.util.FlowUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.flowable.common.engine.impl.identity.Authentication;
import org.flowable.common.engine.impl.util.CollectionUtil;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.history.HistoricProcessInstanceQuery;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ActivityInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.task.Comment;
import org.flowable.identitylink.api.IdentityLink;
import org.flowable.task.api.DelegationState;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskInfo;
import org.flowable.task.api.TaskQuery;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.task.api.history.HistoricTaskInstanceQuery;
import org.flowable.variable.api.history.HistoricVariableInstance;
import org.flowable.variable.api.history.HistoricVariableInstanceQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 工作流任务操作实现类
 *
 * @author Pan Wang
 * @date: 2019/4/11
 */
@Service
@Slf4j
public class FlowTaskServiceImpl implements FlowTaskService {

    @Autowired
    IdentityService identityService;

    @Autowired
    RuntimeService runtimeService;

    @Autowired
    TaskService taskService;

    @Autowired
    FormService formService;

    @Autowired
    HistoryService historyService;

    @Autowired
    RepositoryService repositoryService;

    @Autowired
    FlowProcessDefinitionService flowProcessDefinitionService;

    @Autowired
    ManagementService managementService;

    @Resource
    private UserService userService;

    @Autowired
    public UserTaskAssignService userTaskAssignService;

    @Autowired
    private ProcessEngine processEngine;

    @Autowired
    private OrderInfoService orderInfoService;

    @Autowired
    private SyncProcessStatusService syncProcessStatusService;

    @Autowired
    private WfPlatformDefMapper wfPlatformDefMapper;

    @Autowired
    private WfFormExampleMapper wfFormExampleMapper;

    @Autowired
    private WfFormMapper wfFormMapper;
    @Resource
    private WfUserBusinessRangeService wfUserBusinessRangeService;
    @Resource
    private WfUserSuperiorService wfUserSuperiorService;
    @Resource
    private WfFormTimeConsumingMapper wfFormTimeConsumingMapper;
    @Resource
    private WfTaskAssignMapper wfTaskAssignMapper;
    @Resource
    private WfTaskAssignRoleMapper wfTaskAssignRoleMapper;

    /**
     * 启动流程
     *
     * @param procDefKey 流程定义KEY
     * @param businessId 业务表ID
     * @param vars       变量列表
     * @param userNo     用户编码（统一用户）
     * @return
     */
    @Override
    public String startProcess(String procDefKey, String businessId, Map<String, Object> vars, String userNo) {
        return startProcess(procDefKey, businessId, vars, userNo, null, null);
    }

    /**
     * 启动流程
     *
     * @param procDefKey 流程定义KEY
     * @param businessId 业务表ID
     * @param vars       变量列表
     * @param userNo     用户编码（统一用户）
     * @param deptNo     用户部门
     * @param roleNos    角色编码列表
     * @return
     */
    @Override
    public String startProcess(String procDefKey, String businessId, Map<String, Object> vars, String userNo, String deptNo, List<String> roleNos) {
        return startProcess(procDefKey, businessId, vars, userNo, deptNo, roleNos);
    }

    /**
     * 启动流程
     *
     * @param procDefKey 流程定义KEY
     * @param businessId 业务表ID
     * @param vars       变量列表
     * @param userNo     用户编码（统一用户）
     * @param deptNo     用户部门
     * @param roleNos    角色编码列表
     * @return
     */
    @Override
    public String startProcess(String procDefKey, String businessId, Object formData, Map<String, Object> vars, String userNo, String deptNo, List<String> roleNos) {
        /**
         *  设置流程变量
         */
        if (vars == null) {
            vars = Maps.newHashMap();
        }
        /**
         * 设置流程发起人-可以在后面流程中驳回重新办理
         */
        vars.put(FlowConstant.SUBMITTER, userNo);
        vars.put(FlowConstant.SUBMITTER_DEPT_NO, deptNo);
        vars.put(FlowConstant.SUBMITTER_ROLE_NOS, roleNos);

        {
            //初始化默认的流程变量
            if (vars.get(FlowConstant.COUNTERSIGN_DEFAULT_VAR) == null) {
                vars.put(FlowConstant.COUNTERSIGN_DEFAULT_VAR, Arrays.asList(""));
            }
        }

        /**
         * 设置自定义表单
         */
        if (formData != null) {
            vars.put(FlowConstant.FORM_DATA, formData);
        }

        /**
         * 设置当前流程任务办理人
         */
        Authentication.setAuthenticatedUserId(userNo);

        /**
         * 启动流程
         */
        String procInstanceId = runtimeService.startProcessInstanceByKey(procDefKey, businessId, vars).getId();

        return procInstanceId;
    }


    /**
     * 查询待办列表
     *
     * @param flowDataListDto 流程定义KEY
     * @param userNo          用户编码（统一用户）
     * @return
     */
    @Override
    public FlowDataListDTO<FlowTaskDto> queryTodoList(FlowDataListDTO<FlowTaskDto> flowDataListDto, FlowTaskDto flowTaskDto, String userNo) {
        return queryTodoList(flowDataListDto, flowTaskDto, userNo, null, false);
    }


    /**
     * 构建单条的任务
     *
     * @param needFormData
     * @param task
     * @return
     */
    private FlowTaskDto buildFlowTask(boolean needFormData, Task task) {
        String flowTitle = StringUtils.trimToEmpty((String) task.getProcessVariables().get(FlowConstant.PROCESS_TITLE));
        ProcessDefinition pd = repositoryService.getProcessDefinition(task.getProcessDefinitionId());
        FlowTaskDto flow = FlowTaskDto.builder()
                .categoryName(FlowConstant.DEFAULT_CATEGORY_NAME)
                .category(FlowConstant.DEFAULT_CATEGORY)
                .taskTitle(flowTitle)
                .delegateUserName(task.getOwner())
                .delegateStatus(task.getDelegationState())
                .taskId(task.getId())
                .taskDefKey(task.getTaskDefinitionKey())
                .taskName(task.getName())
                .assignee(task.getAssignee())
                .createTime(task.getCreateTime())
                .procDefId(pd.getId())
                .procDefname(pd.getName())
                .procDefKey(pd.getKey())
                .procDefversion(pd.getVersion())
                .procInsId(task.getProcessInstanceId())
                .claimTime(task.getClaimTime())
                .status(StringUtils.isNotBlank(task.getAssignee()) ? TaskStatusEnum.TODO : TaskStatusEnum.CLAIM)
                .build();
        if (needFormData) {
            flow.setFormData(task.getProcessVariables().getOrDefault(FlowConstant.FORM_DATA, new Object()));
        }
        return flow;
    }

    @Override
    public String userAudit(FlowTaskDto flowTaskDto) {
        Task task = taskService.createTaskQuery().taskId(flowTaskDto.getTaskId()).singleResult();
        String executionId = task.getExecutionId();
        flowTaskDto.setProcInsId(task.getProcessInstanceId());
        //历史留痕
        taskService.setVariableLocal(flowTaskDto.getTaskId(), FlowConstant.AUDIT_PASS, flowTaskDto.getPass());
        if (flowTaskDto.getHandWritingSignatureData() != null) {
            taskService.setVariableLocal
                    (flowTaskDto.getTaskId(), FlowConstant.HAND_WRITING_SIGNATURE_ATTACHMENT_NAME, flowTaskDto.getHandWritingSignatureData());
        }
        try {
            //传递审批操作参数
            Map<String, Object> vars = Maps.newHashMap();
            if (flowTaskDto.getProcessVariable() != null && !flowTaskDto.getProcessVariable().isEmpty()) {
                vars = flowTaskDto.getProcessVariable();
            }
            if (flowTaskDto.getDynamicBusinessScope() != null) {
                vars.put(FlowConstant.SUBMITTER_DEPT_NO, flowTaskDto.getDynamicBusinessScope());
            }
            vars.put(FlowConstant.AUDIT_PASS, flowTaskDto.getPass());
            vars.put(FlowConstant.FORM_DATA, flowTaskDto.getFormData());
            vars.put(FlowConstant.UPDATE_USER, flowTaskDto.getAssignee());
            if (CollectionUtils.isNotEmpty(flowTaskDto.getUserNos())) {
                vars.put(ProcessVariablesEnum.DYNAMIC_USER_ASSIGN.name(), flowTaskDto.getUserNos());
            }
            WfOrder wfOrder = new WfOrder();
            //记录审批备注信息
            if (OrderOperation.PASS.equals(OrderOperation.valueOf(flowTaskDto.getPass()))) {
                log.info("审批通过！：{}", flowTaskDto.getComment());
                wfOrder.setOrderStatus(OrderStatus.PROCESSING.getCode());
                wfOrder.setUpdateTime(DateUtils.getCurrent());
                wfOrder.setUpdateUser(flowTaskDto.getAssigneeName());
                wfOrder.setUpdateUserNo(flowTaskDto.getAssignee());
                orderInfoService.updateWfOrder(flowTaskDto.getProcInsId(), wfOrder);
                taskService.addComment(flowTaskDto.getTaskId(), flowTaskDto.getProcInsId(), "[审批通过] " + flowTaskDto.getComment());
                taskService.complete(flowTaskDto.getTaskId(), vars);
            } else if (OrderOperation.FAIL.equals(OrderOperation.valueOf(flowTaskDto.getPass()))) {
                log.info("审批不通过！：{}", flowTaskDto.getComment());
                wfOrder.setOrderStatus(OrderStatus.FAIL.getCode());
                wfOrder.setCurrentNode("结束");
                wfOrder.setUpdateTime(DateUtils.getCurrent());
                wfOrder.setUpdateUserNo(flowTaskDto.getAssignee());
                wfOrder.setUpdateUser(flowTaskDto.getAssigneeName());
                orderInfoService.updateWfOrder(flowTaskDto.getProcInsId(), wfOrder);
                taskService.addComment(flowTaskDto.getTaskId(), flowTaskDto.getProcInsId(), "[审批不通过] " + flowTaskDto.getComment());
                endProcess(flowTaskDto.getProcInsId(), executionId, vars);
                sendMessage(task, flowTaskDto, vars);
            } else if (OrderOperation.REJECT.equals(OrderOperation.valueOf(flowTaskDto.getPass()))) {
                log.info("审批驳回(可根据orderStatus和流程参数控制节点的流转)！工单状态更新为审批驳回：{}", flowTaskDto.getComment());
                wfOrder.setOrderStatus(OrderStatus.WAITNEWS.getCode());
                wfOrder.setUpdateTime(DateUtils.getCurrent());
                wfOrder.setUpdateUserNo(flowTaskDto.getAssignee());
                wfOrder.setUpdateUser(flowTaskDto.getAssigneeName());
                orderInfoService.updateWfOrder(flowTaskDto.getProcInsId(), wfOrder);
                taskService.addComment(flowTaskDto.getTaskId(), flowTaskDto.getProcInsId(), "[审批驳回] " + flowTaskDto.getComment());
                taskService.complete(flowTaskDto.getTaskId(), vars);
            } else if (OrderOperation.REJECT_TO_UP.equals(OrderOperation.valueOf(flowTaskDto.getPass()))) {
                log.info("驳回到上一级！：{}", flowTaskDto.getComment());
                wfOrder.setOrderStatus(OrderStatus.REJECT.getCode());
                wfOrder.setUpdateTime(DateUtils.getCurrent());
                wfOrder.setUpdateUserNo(flowTaskDto.getAssignee());
                wfOrder.setUpdateUser(flowTaskDto.getAssigneeName());
                orderInfoService.updateWfOrder(flowTaskDto.getProcInsId(), wfOrder);
                taskService.addComment(flowTaskDto.getTaskId(), flowTaskDto.getProcInsId(), "[驳回到上一级] " + flowTaskDto.getComment());
                sendRejectMessage(task, flowTaskDto, vars);
                rejectToUpperTask(flowTaskDto.getProcInsId(), executionId, flowTaskDto.getAssigneeName(), vars);
            } else if (OrderOperation.REJECT_TO_TASK.equals(OrderOperation.valueOf(flowTaskDto.getPass()))) {
                log.info("审批驳回！：{}", flowTaskDto.getComment());
                wfOrder.setOrderStatus(OrderStatus.REJECT.getCode());
                wfOrder.setUpdateTime(DateUtils.getCurrent());
                wfOrder.setUpdateUserNo(flowTaskDto.getAssignee());
                wfOrder.setUpdateUser(flowTaskDto.getAssigneeName());
                orderInfoService.updateWfOrder(flowTaskDto.getProcInsId(), wfOrder);
                taskService.addComment(flowTaskDto.getTaskId(), flowTaskDto.getProcInsId(), "[审批驳回] " + flowTaskDto.getComment());
                sendRejectMessage(task, flowTaskDto, vars);
                rejectToTask(flowTaskDto.getProcInsId(), executionId, flowTaskDto.getTargetActivityId(), vars);
            }
            verifyBusinessScope(flowTaskDto);
        } catch (Exception e) {
            log.error("完成任务失败！释放任务：{}", flowTaskDto, e);
            taskService.unclaim(flowTaskDto.getTaskId());
            throw new APIException(APICode.DATA_ERROR, e.getMessage());
        }
        return executionId;
    }

    private void verifyBusinessScope(FlowTaskDto flowTaskDto) {
        List<Task> list = taskService.createTaskQuery().processInstanceId(flowTaskDto.getProcInsId()).list();
        if (CollectionUtils.isNotEmpty(list)) {
            Task task = list.get(0);
            WfTaskAssign wfTaskAssign = new WfTaskAssign();
            wfTaskAssign.setTaskDefId(task.getTaskDefinitionKey());
            wfTaskAssign.setProcDefId(task.getProcessDefinitionId());
            wfTaskAssign = wfTaskAssignMapper.selectOne(wfTaskAssign);
            log.info("查询当前节点任务分配规则{}", wfTaskAssign);
            if (wfTaskAssign.getTaskDefRule() != null) {
                PersonInfoDto personInfo = userService.getPersonInfo(flowTaskDto.getAssignee(), flowTaskDto.getAppId());
                if (Constants.STATUS_2.equals(wfTaskAssign.getTaskDefRule())) {
                    List<String> businessRangeCodes = personInfo.getBusinessRangeCodes();
                    if (CollectionUtils.isNotEmpty(businessRangeCodes)) {
                        log.info("保存审批人业务范围");
                        wfUserBusinessRangeService.updateOnUserNo(flowTaskDto, personInfo);
                    } else {
                        log.error("下个节点配置有按当前审批人业务范围，当前审批人无业务范围");
                        throw new APIException(APICode.WORKFLOW_SUMBIT_FAIL, "工单审批失败,请审批人配置业务范围！");
                    }
                } else if (Constants.STATUS_4.equals(wfTaskAssign.getTaskDefRule())) {
                    log.info("保存审批人上级信息");
                    wfUserSuperiorService.updateOnUserNo(flowTaskDto.getAssignee(), personInfo);
                }
            }
        }
    }

    private void sendRejectMessage(Task task, FlowTaskDto flowTaskDto, Map<String, Object> vars) {
        ProcessStatusRequest request = new ProcessStatusRequest();
        WfOrder order = orderInfoService.queryWfOrderByPorcessId(flowTaskDto.getProcInsId());
        request.setProcessDefKey(order.getProcDefKey());
        request.setProcessId(flowTaskDto.getProcInsId());
        if (vars != null && vars.get(FlowConstant.AUDIT_PASS) != null) {
            request.setOperation((String) vars.get(FlowConstant.AUDIT_PASS));
        }
        HistoricActivityInstance historicActivityInstance = getHistTask(flowTaskDto.getProcInsId()).get(1);
        request.setPreviousNode(historicActivityInstance.getActivityName());
        request.setCurrentNode(task.getName());
        request.setIndex_1(order.getIndex_1());
        request.setIndex_2(order.getIndex_2());
        request.setIndex_3(order.getIndex_3());
        request.setUserNo(flowTaskDto.getAssignee());
        request.setTaskId(task.getId());
        request.setLogo(FlowConstant.END);
        request.setMessageType(MessageTypeEnum.USER_TASK.getType());
        request.setSubmitUser(order.getCreateUserNo());
        request.setOrderId(order.getOrderId());
        request.setTaskDefId(task.getTaskDefinitionKey());
        request.setExecutionId(task.getExecutionId());
        request.setProcessDefId(task.getProcessDefinitionId());
        request.setStatus(OrderStatus.getEnum(order.getOrderStatus()));
        if (StringUtils.isNotBlank(task.getExecutionId())) {
            String hisTaskId = historyService.createHistoricTaskInstanceQuery().executionId(task.getExecutionId()).orderByTaskCreateTime().desc().list().get(0).getId();
            log.info("历史任务ID={}", hisTaskId);
            if (StringUtils.isNotBlank(hisTaskId)) {
                List<Comment> commentList = taskService.getTaskComments(hisTaskId);
                if (CollectionUtils.isNotEmpty(commentList)) {
                    List<String> messageList = commentList.stream().map(Comment::getFullMessage).collect(Collectors.toList());
                    request.setComments(messageList);
                }
            }
        }
        WfPlatformDef wfPlatformDef = null;
        {
            log.info("【同步系统信息】获取平台信息！appId：{}，processId：{}", flowTaskDto.getAppId(), request.getProcessId());
            Example example2 = new Example(WfPlatformDef.class);
            example2.createCriteria().andEqualTo("platformId", flowTaskDto.getAppId());
            wfPlatformDef = wfPlatformDefMapper.selectOneByExample(example2);
            request.setUpdateTime(DateUtils.formatDate(DateUtils.getCurrent(), DateUtils.FORMAT_TIME));
        }
        if (wfPlatformDef.getType() == 0) {
            WfFormExample wfFormExample = wfFormExampleMapper.selectByProcessId(request.getProcessId(), task.getFormKey());
            if (wfFormExample != null) {
                String formData = wfFormExample.getProcessData();
                request.setFormData(formData);
            } else {
                log.info("【同步系统信息】无表单数据！appId：{}，processId：{}", flowTaskDto.getAppId(), request.getProcessId());
            }
        }
        if (flowTaskDto.getAppId() != null) {
            log.info("【完成任务节点】同步流程状态。节点={}，操作={}，状态={}", task.getName(), request.getOperation(), request.getStatus());
            syncProcessStatusService.syncProcessStatus(flowTaskDto.getAppId(), request);
        }
    }


    private void sendMessage(Task task, FlowTaskDto flowTaskDto, Map<String, Object> vars) {
        log.info("审批不通过！appId={}，processId={}， vars={}", flowTaskDto.getAppId(), flowTaskDto.getProcInsId(), vars);
        sendRejectMessage(task, flowTaskDto, vars);
    }

    private List<HistoricActivityInstance> getHistTask(String processesId) {
        List<HistoricActivityInstance> collect = historyService.createHistoricActivityInstanceQuery().processInstanceId(processesId)
                .orderByHistoricActivityInstanceEndTime().desc().list();
        List<HistoricActivityInstance> list = new ArrayList<>();
        collect.forEach(historicTaskInstance -> {
            if ("startEvent".equals(historicTaskInstance.getActivityType()) || "userTask".equals(historicTaskInstance.getActivityType())) {
                list.add(historicTaskInstance);
            }
        });
        return list;
    }

    @Override
    public void rejectToUpperTask(String procInsId, String executionId, String assigneeName, Map<String, Object> vars) {
        runtimeService.setVariables(executionId, vars);
        processEngine.getManagementService().executeCommand(new CommonJumpToUpperTaskCmd(procInsId, executionId, assigneeName));
    }

    @Override
    public void rejectToTask(String procInsId, String executionId, String targetActivityId, Map<String, Object> vars) {
        runtimeService.setVariables(executionId, vars);
        processEngine.getManagementService().executeCommand(new CommonJumpTaskCmd(procInsId, executionId, targetActivityId));
    }

    @Override
    public void endProcess(String processInstId, String executionId, Map<String, Object> vars) {
        runtimeService.setVariables(executionId, vars);
        processEngine.getManagementService().executeCommand(new CommonEndProcessInstanceCmd(processInstId));
    }

    /**
     * 删除任务
     *
     * @param taskId       任务ID
     * @param deleteReason 删除原因
     */
    @Override
    public void deleteTask(String taskId, String deleteReason) {
        taskService.deleteTask(taskId, deleteReason);
    }

    /**
     * 签收任务
     *
     * @param taskId 任务ID
     * @param userNo 签收用户ID（用户登录名）
     */
    @Override
    public void claim(String taskId, String userNo) {
        taskService.claim(taskId, userNo);
    }

    /**
     * 委托他人完成任务
     *
     * @param taskId 任务ID
     * @param userNo 被委托人
     */
    @Override
    public void delegateTask(String taskId, String userNo) {
        taskService.delegateTask(taskId, userNo);
    }

    /**
     * 转派他人完成
     *
     * @param taskId 任务ID
     * @param userNo 被委托人
     * @param reason 原因
     */
    @Override
    public void transferTask(String taskId, String userNo, String reason) {
        Task task = getTask(taskId);
        taskService.addComment(taskId, task.getProcessInstanceId(), "[转派] " + reason);
        taskService.setAssignee(taskId, userNo);
    }

    /**
     * 取消签收任务
     *
     * @param taskId 任务ID
     * @param userNo 签收用户ID（用户登录名）
     */
    @Override
    public void unclaim(String taskId, String userNo) {
        taskService.unclaim(taskId);
    }

    /**
     * 提交任务, 并保存意见
     *
     * @param vars 任务变量
     */
    @Override
    public void complete(FlowTaskDto flowTaskDto, Map<String, Object> vars) {
        String taskId = flowTaskDto.getTaskId();
        String comment = flowTaskDto.getComment();
        // 设置流程变量
        if (vars == null) {
            vars = Maps.newHashMap();
        }
        Task task = getTask(taskId);
        String procInsId = task.getProcessInstanceId();
        //是否委托
        boolean delegation = task.getDelegationState() != null && DelegationState.PENDING == task.getDelegationState();
        // 添加意见
        if (StringUtils.isNotBlank(procInsId) && StringUtils.isNotBlank(comment)) {
            if (delegation) {
                taskService.addComment(taskId, procInsId, "[委托] " + comment);
            } else {
                taskService.addComment(taskId, procInsId, comment);
            }
        }
        if (delegation) {
            // 完成任务委托
            taskService.resolveTask(taskId, vars);
        } else {
            // 完成提交任务
            taskService.complete(taskId, vars);
        }
    }


    /**
     * 查询待办列表
     *
     * @param flowDataListDto 流程定义KEY
     * @param userNo          用户编码（统一用户）
     * @param roleNos         角色编码列表
     * @return
     */
    @Override
    public FlowDataListDTO<FlowTaskDto> queryTodoList(FlowDataListDTO<FlowTaskDto> flowDataListDto, FlowTaskDto flowTaskDto, String userNo, List<String> roleNos, boolean needFormData) {
        /**
         * 构建任务查询物件
         */
        TaskQuery todoTaskQuery = buildQuery(flowTaskDto);

        /**
         * 单人或用户组待签收/待办理
         */
        FlowUtils.buildTodoQuery(todoTaskQuery, userNo, roleNos);

        /**
         * 按照任务创建日期倒叙排
         */
        todoTaskQuery.orderByTaskCreateTime().desc();

        /**
         * 设置总记录数
         */
        flowDataListDto.setCount(todoTaskQuery.count());

        /**
         * 查询任务列表
         */
        List<Task> listPage = todoTaskQuery.listPage(flowDataListDto.getFirstResult(), flowDataListDto.getPageSize());

        /**
         * 返回任务列表
         */
        flowDataListDto.setData(buildFlowTasks(listPage, needFormData));

        return flowDataListDto;
    }

    /**
     * 封装任务列表
     *
     * @param listPage
     * @param needFormData
     * @return
     */
    private List<FlowTaskDto> buildFlowTasks(List<Task> listPage, boolean needFormData) {
        List<FlowTaskDto> flowList = new ArrayList<>();
        for (Task task : listPage) {
            FlowTaskDto flow = buildFlowTask(needFormData, task);
            flowList.add(flow);
        }
        return flowList;
    }

    /**
     * 查询单个任务
     *
     * @param taskId
     * @return
     */
    @Override
    public FlowTaskDto getTaskById(String taskId) {
        return buildFlowTask(true, this.taskService.createTaskQuery().taskId(taskId).singleResult());
    }


    /**
     * 获得下一个节点的审批任务
     *
     * @param processId 流程实例id
     * @return
     * @throws Exception
     */
    @Override
    public FlowTaskDto getNextTask(String processId) {
        List<Task> list = ((TaskQuery) ((TaskQuery) ((TaskQuery) this.taskService.createTaskQuery()
                .processInstanceId(processId)).orderByTaskCreateTime())
                .desc()).list();
        FlowTaskDto flow = null;
        if (!CollectionUtils.isEmpty(list)) {
            Task task = list.get(0);
            flow = buildFlowTask(true, task);
        }
        return flow;
    }


    /**
     * 构建任务查询物件
     *
     * @param flowTaskDto
     * @return
     */
    private TaskQuery buildQuery(FlowTaskDto flowTaskDto) {
        TaskQuery query = taskService.createTaskQuery().includeProcessVariables().active();
        if (StringUtils.isNotBlank(flowTaskDto.getProcDefKey())) {
            query.taskDefinitionKey(flowTaskDto.getProcDefKey());
        }
        if (flowTaskDto.getBeginDate() != null) {
            query.taskCreatedAfter(flowTaskDto.getBeginDate());
        }
        if (flowTaskDto.getEndDate() != null) {
            query.taskCreatedBefore(flowTaskDto.getEndDate());
        }
        return query;
    }

    /**
     * 获取已发任务
     *
     * @param flowDataListDto
     * @param userNo
     * @return
     */
    @Override
    public FlowDataListDTO querySendedList(FlowDataListDTO<FlowTaskDto> flowDataListDto, FlowTaskDto flowTaskDto, String userNo) {

        HistoricProcessInstanceQuery historyProQuery = historyService.createHistoricProcessInstanceQuery().startedBy(userNo).orderByProcessInstanceStartTime().desc();

        /**
         * 查询总数
         */
        flowDataListDto.setCount(historyProQuery.count());

        /**
         *  查询列表
         */
        List<HistoricProcessInstance> hispList = historyProQuery.listPage(flowDataListDto.getFirstResult(), flowDataListDto.getPageSize());

        /**
         * 处理分页问题
         */
        List<FlowTaskDto> actList = Lists.newArrayList();
        for (HistoricProcessInstance hisprocIns : hispList) {
            System.out.println(hisprocIns.getProcessVariables());
            FlowTaskDto flow = new FlowTaskDto();
            ProcessDefinition pd = repositoryService.getProcessDefinition(hisprocIns.getProcessDefinitionId());
//            Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(pd.getDeploymentId()).singleResult();
            flow.setCategoryName(FlowConstant.DEFAULT_CATEGORY_NAME);
            flow.setCategory(FlowConstant.DEFAULT_CATEGORY);
            flow.setProcDefId(pd.getId());
            flow.setProcDefname(pd.getName());
            flow.setProcDefKey(pd.getKey());
            flow.setProcDefversion(pd.getVersion());
            flow.setProcInsId(hisprocIns.getId());
            HistoricVariableInstance historicVariableInstance = historyService.createHistoricVariableInstanceQuery().processInstanceId(hisprocIns.getId()).variableName(FlowConstant.PROCESS_TITLE).singleResult();
            flow.setCreateTime(hisprocIns.getStartTime());
            flow.setEndTime(hisprocIns.getEndTime());
            flow.setTaskTitle(Objects.nonNull(historicVariableInstance.getValue()) ? historicVariableInstance.getValue().toString() : null);
            flow.setBusinessId(hisprocIns.getBusinessKey());
            flow.setHisActInsActName(hisprocIns.getName());
            flow.setProcInsId(hisprocIns.getId());
            flow.setHisProcInsId(hisprocIns.getId());
            flow.setProcessFinished(hisprocIns.getEndActivityId() != null);
            flow.setStatus(TaskStatusEnum.FINISH);
            flow.setTaskId(historicVariableInstance.getTaskId());
            actList.add(flow);
        }
        flowDataListDto.setData(actList);
        return flowDataListDto;
    }

    /**
     * 获取已办任务
     *
     * @return
     */
    @Override
    public FlowDataListDTO<FlowTaskDto> queryHistoryTaskList(FlowDataListDTO<FlowTaskDto> flowDataListDto, FlowTaskDto flowTaskDto, String userNo) {
        HistoricTaskInstanceQuery histTaskQuery = historyService.createHistoricTaskInstanceQuery().taskAssignee(userNo).finished()
                .includeProcessVariables().orderByHistoricTaskInstanceEndTime().desc();
        // 设置查询条件
        if (StringUtils.isNotBlank(flowTaskDto.getProcDefKey())) {
            histTaskQuery.processDefinitionKey(flowTaskDto.getProcDefKey());
        }
        if (flowTaskDto.getBeginDate() != null) {
            histTaskQuery.taskCompletedAfter(flowTaskDto.getBeginDate());
        }
        if (flowTaskDto.getEndDate() != null) {
            histTaskQuery.taskCompletedBefore(flowTaskDto.getEndDate());
        }
        // 查询总数
        flowDataListDto.setCount(histTaskQuery.count());
        // 查询列表
        List<HistoricTaskInstance> histList = histTaskQuery.listPage(flowDataListDto.getFirstResult(), flowDataListDto.getPageSize());
        //处理分页问题
        List<FlowTaskDto> actList = Lists.newArrayList();
        for (HistoricTaskInstance histTask : histList) {
            String flowTitle = StringUtils.trimToEmpty((String) (histTask.getProcessVariables().get(FlowConstant.PROCESS_TITLE)));
            ProcessDefinition pd = repositoryService.getProcessDefinition(histTask.getProcessDefinitionId());
            HistoricProcessInstance historicTaskInstance = getHistoryProcIns(histTask.getProcessInstanceId());
            List<HistoricVariableInstance> historicVariableInstance = historyService.createHistoricVariableInstanceQuery().processInstanceId(histTask.getProcessInstanceId()).listPage(1, 100);

            FlowTaskDto flow = FlowTaskDto.builder()
                    .categoryName(FlowConstant.DEFAULT_CATEGORY_NAME)
                    .category(FlowConstant.DEFAULT_CATEGORY)
                    .taskTitle(flowTitle)
                    .delegateUserName(histTask.getOwner())
                    .taskId(histTask.getId())
                    .taskDefKey(histTask.getTaskDefinitionKey())
                    .taskName(histTask.getName())
                    .assignee(histTask.getAssignee())
                    .createTime(histTask.getCreateTime())
                    .endDate(histTask.getEndTime())
                    .procDefId(pd.getId())
                    .procDefname(pd.getName())
                    .procDefKey(pd.getKey())
                    .procDefversion(pd.getVersion())
                    .procInsId(histTask.getProcessInstanceId())
                    .hisProcInsId(histTask.getProcessInstanceId())
                    .processFinished(historicTaskInstance.getEndActivityId() != null)
                    .status(TaskStatusEnum.FINISH)
                    .build();
            actList.add(flow);
        }
        flowDataListDto.setData(actList);
        return flowDataListDto;
    }


    @Override
    public List<UserTaskDto> queryProcessUserTasks(String procInsId) {
        log.info("根据processId获取历史任务");
        List<UserTaskDto> list = Lists.newArrayList();
        List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery().processInstanceId(procInsId).list();
        if (CollectionUtils.isNotEmpty(historicTaskInstanceList)) {
            log.info("根据processDefinitionId获取当前流程得任务节点");
            List<WfTaskAssign> taskList = userTaskAssignService.queryProAllTaskDefInfo(procInsId, historicTaskInstanceList.get(0).getProcessDefinitionId());
            log.info("根据processId获取当前流程历史流转节点");
            List<FlowTaskHistoryDTO> flowTaskHistoryDtoList = queryTaskHistories(procInsId);
            Map<String, List<FlowTaskHistoryDTO>> srouceMap = flowTaskHistoryDtoList.stream().collect(Collectors.groupingBy(FlowTaskHistoryDTO::getTaskDefKey));
            if (CollectionUtils.isNotEmpty(taskList)) {
                for (WfTaskAssign taskInfo : taskList) {
                    UserTaskDto userDto = new UserTaskDto();
                    userDto.setTaskName(taskInfo.getTaskDefKey());
                    userDto.setTaskDefKey(taskInfo.getTaskDefId());
                    List<FlowTaskHistoryDTO> hitList = srouceMap.get(taskInfo.getTaskDefId());
                    if (CollectionUtil.isNotEmpty(hitList)) {
                        log.info("获取当前节点的第一次开始时间");
                        Optional<FlowTaskHistoryDTO> min = hitList.stream().min((a, b) -> a.getStartTime().compareTo(b.getStartTime()));
                        if (min.isPresent()) {
                            FlowTaskHistoryDTO source = min.get();
                            userDto.setCreateTime(source.getStartTime());
                        }

                        log.info("获取当前节点最后一次的修改人与修改时间");
                        Optional<FlowTaskHistoryDTO> optional = hitList.stream().max((a, b) -> a.getEndTime().compareTo(b.getEndTime()));
                        if (optional.isPresent()) {
                            FlowTaskHistoryDTO source = optional.get();
                            userDto.setAuditOperation(source.getAuditOperation());
                            if (source.getTaskName().contains("[会签]")) {
                                userDto.setUserName("多人");
                            } else {
                                userDto.setUserName(source.getAssigneeName());
                            }
                            userDto.setUpdateTime(source.getEndTime());
                            log.info("一个节点多人审批时耗时总和");
                            long millisecond = 0;
                            for (FlowTaskHistoryDTO flowTaskHistoryDTO : hitList) {
                                millisecond += Long.parseLong(flowTaskHistoryDTO.getTimeConsuming()) / 1000 * 1000;
                            }
                            userDto.setTimeConsuming(DateUtil.getDistanceTime(millisecond));

                        }
                    } else {
                        List<ActivityInstance> list1 = runtimeService.createActivityInstanceQuery().processInstanceId(procInsId).list();
                        List<ActivityInstance> collect = list1.stream().filter(a -> a.getEndTime() == null).collect(Collectors.toList());
                        if (CollectionUtils.isNotEmpty(collect)) {
                            ActivityInstance activityInstance = collect.get(0);
                            if (taskInfo.getTaskDefKey().equals(activityInstance.getActivityName())) {
                                userDto.setCreateTime(activityInstance.getStartTime());
                            }
                        }

                    }
                    list.add(userDto);
                }
            }
        }
        return list;
    }

    /**
     * 获取流转历史列表
     *
     * @param procInsId 流程实例
     */
    @Override
    public List<FlowTaskHistoryDTO> queryTaskHistories(String procInsId) {
        List<FlowTaskHistoryDTO> actList = Lists.newArrayList();
        log.info("得到所有的历史流转节点,之中的结束节点");
        List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery().processInstanceId(procInsId).list();
        WfOrder order = orderInfoService.queryWfOrderByPorcessId(procInsId);
        log.info("历史流转的userTask");
        List<HistoricTaskInstance> collect = historyService.createHistoricTaskInstanceQuery().processInstanceId(procInsId).orderByHistoricTaskInstanceEndTime().asc().list();
        List<String> assigneeList = new ArrayList<>();

        for (HistoricTaskInstance hisTask : collect) {
            if (hisTask.getEndTime() != null && hisTask.getAssignee() != null) {
                assigneeList.add(hisTask.getAssignee());
                FlowTaskHistoryDTO target = new FlowTaskHistoryDTO();
                target.setNodeType("用户节点");
                target.setTaskName(hisTask.getName());
                target.setTaskId(hisTask.getId());
                target.setProcessId(hisTask.getProcessInstanceId());
                target.setTaskDefKey(hisTask.getTaskDefinitionKey());
                List<Comment> commentList = taskService.getTaskComments(hisTask.getId());
                if (CollectionUtils.isNotEmpty(commentList)) {
                    String fullMessage = commentList.stream().map(Comment::getFullMessage).collect(Collectors.joining("\r\n"));
                    target.setAuditComment(fullMessage);
                }
                target.setAssignee(hisTask.getAssignee());
                HistoricVariableInstanceQuery historicVariableInstanceQuery = historyService.createHistoricVariableInstanceQuery().taskId(hisTask.getId());
                HistoricVariableInstance hisVarInstance = historicVariableInstanceQuery.variableName(FlowConstant.AUDIT_PASS).singleResult();
                if (hisVarInstance != null && hisVarInstance.getValue() != null) {
                    target.setAuditOperation(OrderOperation.valueOf((String) hisVarInstance.getValue()).getRemark());
                    String string = OrderOperation.valueOf((String) hisVarInstance.getValue()).toString();
                    if (OrderStatus.PASS.toString().equals(string)) {
                        target.setOrderStruts(OrderStatus.PASS.getCode());
                    } else if (OrderStatus.FAIL.toString().equals(string)) {
                        target.setOrderStruts(OrderStatus.FAIL.getCode());
                    } else if (OrderStatus.REJECT.toString().equals(string)) {
                        target.setOrderStruts(OrderStatus.REJECT.getCode());
                    }
                }

                hisVarInstance = historicVariableInstanceQuery.variableName(FlowConstant.HAND_WRITING_SIGNATURE_ATTACHMENT_NAME).singleResult();
                if (hisVarInstance != null && hisVarInstance.getValue() != null) {
                    target.setHandWritingSignatureData((Map<String, String>) hisVarInstance.getValue());
                }

                {
                    log.info("表单耗时");
                    WfFormTimeConsuming wfFormTimeConsuming = new WfFormTimeConsuming();
                    wfFormTimeConsuming.setTaskTd(hisTask.getId());
                    wfFormTimeConsuming = wfFormTimeConsumingMapper.selectOne(wfFormTimeConsuming);
                    if (wfFormTimeConsuming != null) {
                        String distanceTime = DateUtil.getDistanceTime(Long.parseLong(wfFormTimeConsuming.getTimeConsuming().toString()));
                        target.setTimeOnForm(distanceTime);
                    }
                }
                target.setStartTime(hisTask.getCreateTime());
                target.setEndTime(hisTask.getEndTime());
                if (hisTask.getDurationInMillis() != null) {
                    target.setTimeConsuming(hisTask.getDurationInMillis().toString());
                }

                if (hisTask.getFormKey() != null) {
                    WfForm wfForm = new WfForm();
                    wfForm.setFormCode(hisTask.getFormKey());
                    wfForm = wfFormMapper.selectOne(wfForm);
                    target.setFormName(wfForm.getFormName());
                }
                actList.add(target);
            }
        }
        log.info("获取结束节点信息");
        for (HistoricActivityInstance hisActTask : list) {
            if ("endEvent".equals(hisActTask.getActivityType()) && hisActTask.getEndTime() != null) {
                FlowTaskHistoryDTO target = new FlowTaskHistoryDTO();
                target.setNodeType("结束节点");
                target.setTaskName(hisActTask.getActivityName());
                target.setTaskDefKey(hisActTask.getActivityId());
                target.setTimeConsuming(DateUtil.getDistanceTime(hisActTask.getDurationInMillis()));
                target.setStartTime(hisActTask.getStartTime());
                target.setEndTime(hisActTask.getEndTime());
                actList.add(target);
            }
        }
        log.info("根据userNo统一获取用户信息（放在循环外调用统一登陆）");
        if (CollectionUtils.isNotEmpty(assigneeList)) {
            HashSet<String> h = new HashSet<>(assigneeList);
            assigneeList.clear();
            assigneeList.addAll(h);
            PersonInfoWithAppReq req = new PersonInfoWithAppReq();
            req.setAppId(order.getAppId());
            req.setUserNoList(assigneeList);
            List<AppUserResp> personInfos = userService.getPersonWithBusinessList(req);
            if (CollectionUtils.isNotEmpty(personInfos)) {
                Map<String, String> userMap = personInfos.stream().collect(Collectors.toMap(AppUserResp::getUserNo, AppUserResp::getUserName));
                List<FlowTaskHistoryDTO> flowTaskHistoryDTOList = Lists.newArrayList();
                for (FlowTaskHistoryDTO flowTaskHistoryDTO : actList) {
                    flowTaskHistoryDTO.setAssigneeName(userMap.get(flowTaskHistoryDTO.getAssignee()));
                    flowTaskHistoryDTOList.add(flowTaskHistoryDTO);
                }
                return flowTaskHistoryDTOList;
            }
        }

        return actList;
    }


    @Override
    public List<FlowTaskHistoryDTO> queryHistoriesOfLevel(String processId, String showLevel) {
        List<FlowTaskHistoryDTO> listA = queryTaskHistories(processId);
        if (StringUtils.isBlank(showLevel)
                || "A".equals(showLevel)) {
            return listA;
        } else if ("B".equals(showLevel)) {
            List<FlowTaskHistoryDTO> intermediateCatchEventList = queryIntermediateCatchEventHistories(processId);
            if (CollectionUtils.isNotEmpty(intermediateCatchEventList)) {
                listA.addAll(intermediateCatchEventList);
                return listA.stream().sorted((FlowTaskHistoryDTO o1, FlowTaskHistoryDTO o2) -> {
                    return o1.getEndTime().compareTo(o2.getEndTime());
                }).collect(Collectors.toList());
            }
        }
        return listA;
    }

    @Override
    public List<String> getCandidate(Task task) {
        List<String> nameList = new ArrayList<>();
        if (StringUtils.isNotBlank(task.getFormKey())) {
            if (task.getAssignee() != null) {
                log.info("获取当前节点领取任务人信息");
                PersonInfoDto personInfo = userService.getPersonInfo(task.getAssignee(), "");
                nameList.add(personInfo.getName());
                return nameList;
            } else {
                List<IdentityLink> identityLinksForTask = taskService.getIdentityLinksForTask(task.getId());
                List<String> userNoList = identityLinksForTask.stream().map(IdentityLink::getUserId).filter(StringUtils::isNotBlank).collect(Collectors.toList());
                List<String> groupIdList = identityLinksForTask.stream().map(IdentityLink::getGroupId).filter(StringUtils::isNotBlank).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(userNoList)) {
                    log.info("获取当前节点候选人");
                    PersonInfoReq req = new PersonInfoReq();
                    req.setUserNoList(userNoList);
                    List<PersonInfoDto> personInfos = userService.getPersonInfos(req);
                    List<String> collect = personInfos.stream().map(PersonInfoDto::getName).collect(Collectors.toList());
                    nameList.addAll(collect);
                } else if (CollectionUtils.isNotEmpty(groupIdList)) {
                    log.info("获取当前节点候选组");
                    Example example = new Example(WfTaskAssignRole.class);
                    Example.Criteria criteria = example.createCriteria();
                    groupIdList.forEach(groupId -> {
                        criteria.orEqualTo("roleCode", groupId);
                    });
                    List<WfTaskAssignRole> wfTaskAssignRoles = wfTaskAssignRoleMapper.selectByExample(example);
                    List<String> collect = wfTaskAssignRoles.stream().map(WfTaskAssignRole::getRoleName).collect(Collectors.toList());
                    LinkedHashSet<String> linked = new LinkedHashSet<>(collect);
                    List<String> linkedList = new ArrayList<>(linked);
                    nameList.addAll(linkedList);
                }
            }
        }
        return nameList;
    }


    private List<FlowTaskHistoryDTO> queryIntermediateCatchEventHistories(String processId) {
        List<FlowTaskHistoryDTO> resultList = new ArrayList<>();
        List<HistoricActivityInstance> intermediateCatchEventList =
                historyService.createHistoricActivityInstanceQuery().processInstanceId(processId).activityType("intermediateCatchEvent").finished().list();
        if (CollectionUtils.isNotEmpty(intermediateCatchEventList)) {
            List<String> assigneeList = new ArrayList<>();
            intermediateCatchEventList.forEach(action -> {
                if (action.getAssignee() != null) {
                    assigneeList.add(action.getAssignee());
                }
                FlowTaskHistoryDTO hisDTO = new FlowTaskHistoryDTO();
                hisDTO.setTaskName(action.getActivityName());
                hisDTO.setTaskDefKey(action.getActivityId());
                hisDTO.setNodeType("消息节点");
                if (action.getDurationInMillis() != null) {
                    hisDTO.setTimeConsuming(action.getDurationInMillis().toString());
                }
                hisDTO.setStartTime(action.getStartTime());
                hisDTO.setEndTime(action.getEndTime());
                HistoricVariableInstance hisVarInstance = historyService.createHistoricVariableInstanceQuery().executionId(action.getExecutionId()).variableName(action.getId()).singleResult();
                if (hisVarInstance != null) {
                    hisDTO.setAuditComment((String) hisVarInstance.getValue());
                }
                resultList.add(hisDTO);
            });

            if (CollectionUtils.isNotEmpty(assigneeList)) {
                HashSet<String> h = new HashSet<>(assigneeList);
                assigneeList.clear();
                assigneeList.addAll(h);
                PersonInfoReq req = new PersonInfoReq();
                req.setUserNoList(assigneeList);
                List<UserDTO> personInfos = userService.getPersonInfos(null, req);
                if (CollectionUtils.isNotEmpty(personInfos)) {
                    Map<String, String> userMap = personInfos.stream().collect(Collectors.toMap(UserDTO::getUserNo, UserDTO::getName));
                    List<FlowTaskHistoryDTO> flowTaskHistoryDTOList = Lists.newArrayList();
                    for (FlowTaskHistoryDTO flowTaskHistoryDTO : resultList) {
                        flowTaskHistoryDTO.setAssigneeName(userMap.get(flowTaskHistoryDTO.getAssignee()));
                        flowTaskHistoryDTOList.add(flowTaskHistoryDTO);
                    }
                    return flowTaskHistoryDTOList;
                }
            }

        }
        return resultList;
    }

    /**
     * 获取流程表单（首先获取任务节点表单KEY，如果没有则取流程开始节点表单KEY）
     *
     * @return
     */
    @Override
    public String getFormKey(String procDefId, String taskDefKey) {
        String formKey = "";
        if (StringUtils.isNotBlank(procDefId)) {
            try {
                if (StringUtils.isNotBlank(taskDefKey)) {
                    formKey = formService.getTaskFormKey(procDefId, taskDefKey);
                }
            } catch (Exception e) {
                formKey = "";
            }
            if (StringUtils.isBlank(formKey)) {
                formKey = formService.getStartFormKey(procDefId);
            }
        }
        log.debug("getFormKey: %s", formKey);
        return formKey;
    }

    /**
     * 获取流程实例对象
     *
     * @param procInsId
     * @return
     */
    @Override
    public ProcessInstance getProcIns(String procInsId) {
        return runtimeService.createProcessInstanceQuery().processInstanceId(procInsId).singleResult();
    }

    /**
     * 获取历史流程实例对象
     *
     * @param procInsId
     * @return
     */
    @Override
    public HistoricProcessInstance getHistoryProcIns(String procInsId) {
        return historyService.createHistoricProcessInstanceQuery().processInstanceId(procInsId).singleResult();
    }


    /**
     * 获取任务
     *
     * @param taskId 任务ID
     */
    @Override
    public Task getTask(String taskId) {
        return taskService.createTaskQuery().taskId(taskId).singleResult();
    }

    /**
     * 获取历史任务
     *
     * @param taskId 任务ID
     */
    @Override
    public HistoricTaskInstance getHistoryTask(String taskId) {
        return historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
    }

    @Override
    public TaskInfo getTaskOrHistoryTask(String taskId) {
        TaskInfo taskInfo = getTask(taskId);
        if (taskInfo == null) {
            taskInfo = getHistoryTask(taskId);
        }
        return taskInfo;
    }

    /**
     * 获取历史任务
     *
     * @param procInsId 流程实例ID
     */
    @Override
    public HistoricTaskInstance getHistoryTaskByProcessInstanceId(String procInsId) {
        return historyService.createHistoricTaskInstanceQuery().processInstanceId(procInsId).orderByHistoricTaskInstanceEndTime().desc().list().get(0);
    }


    /**
     * 查询业务表ID
     *
     * @param procInsId
     * @return
     */
    @Override
    public String getBusinessKeyId(String procInsId) {
        ProcessInstance procIns = getProcIns(procInsId);
        if (procIns != null) {
            return procIns.getBusinessKey();
        } else {
            HistoricProcessInstance history = getHistoryProcIns(procInsId);
            if (history != null) {
                return history.getBusinessKey();
            }
        }
        return null;
    }

    @Override
    public PageInfo<Task> pageQueryToDoTaskList(String userNo, Integer pageNum, Integer pageSize) {
        PageInfo<Task> pageInfo = new PageInfo<>();
        List<Task> taskList = taskService.createTaskQuery().taskInvolvedUser(userNo).listPage(pageSize * (pageNum - 1), pageSize);
        Long total = taskService.createTaskQuery().taskInvolvedUser(userNo).count();
        pageInfo.setTotal(total);
        pageInfo.setPageNum(pageNum);
        pageInfo.setPageSize(pageSize);
        pageInfo.setList(taskList);
        return pageInfo;
    }

    @Override
    public PageInfo<HistoricTaskInstance> pageQueryDoneTaskList(String userNo, Integer pageNum, Integer pageSize) {
        PageInfo<HistoricTaskInstance> pageInfo = new PageInfo<>();
        List<HistoricTaskInstance> taskList
                = historyService.createHistoricTaskInstanceQuery().taskInvolvedUser(userNo).listPage(pageSize * (pageNum - 1), pageSize);
        Long total = historyService.createHistoricTaskInstanceQuery().taskInvolvedUser(userNo).count();
        pageInfo.setTotal(total);
        pageInfo.setPageNum(pageNum);
        pageInfo.setPageSize(pageSize);
        pageInfo.setList(taskList);
        return pageInfo;
    }

    @Override
    public void unclaim(String taskId) {
        log.info("释放已领取任务！{}", taskId);
        taskService.unclaim(taskId);
    }


}
